package com.lhd.service.impl;

import java.time.Duration;
import java.time.LocalDateTime;
import java.util.*;

import javax.annotation.Resource;

import cn.hutool.core.bean.BeanUtil;
import com.lhd.component.RedisComponent;
import com.lhd.entity.constants.Constants;
import com.lhd.entity.dto.AdditionInfoDto;
import com.lhd.entity.dto.LocationDto;
import com.lhd.entity.dto.SubmitDto;
import com.lhd.entity.enums.*;
import com.lhd.entity.po.Activity;
import com.lhd.entity.query.ActivityQuery;
import com.lhd.exception.BusinessException;
import com.lhd.mappers.ActivityMapper;
import org.springframework.stereotype.Service;

import com.lhd.entity.query.RecordQuery;
import com.lhd.entity.po.Record;
import com.lhd.entity.vo.PaginationResultVO;
import com.lhd.entity.query.SimplePage;
import com.lhd.mappers.RecordMapper;
import com.lhd.service.RecordService;
import com.lhd.utils.StringTools;

/**
 * @Author: liuhd
 * @Date: 2025/03/16
 * @Description: Record业务接口实现类
 */
@Service
public class RecordServiceImpl implements RecordService { 
	@Resource
	private RecordMapper<Record, RecordQuery> recordMapper;
	@Resource
	private ActivityMapper<Activity, ActivityQuery> activityMapper;
	@Resource
	private RedisComponent redisComponent;
	/**
	 * 根据条件查询列表
	 */
	@Override
	public List<Record> findListByQuery(RecordQuery query){
		return recordMapper.selectList(query);
	}

	/**
	 * 根据条件查询数量
	 */
	@Override
	public Long findCountByQuery(RecordQuery query){
		return recordMapper.selectCount(query);
	}

	/**
	 * 分页查询
	 */
	@Override
	public PaginationResultVO<Record> findListByPage(RecordQuery query){
		// 查出查询的结果数量
		long count = findCountByQuery(query);
		// 如果没给pageSize 默认是15
		long pageSize = query.getPageSize() == null ? PageSize.SIZE15.getSize() : query.getPageSize();
		// 构建SimplePage 可以确定limit的index与offset以及总页数 以及真正的pageNo
		SimplePage page = new SimplePage(query.getPageNo(), count, pageSize);
		// 设置到query中 xml中会使用query.simplePage.start与query.simplePage.end
		query.setSimplePage(page);
		// 用query查询 此时是分页条件查询
		List<Record> list = this.findListByQuery(query);
		// 将结果塞到PaginationResultVO中
		PaginationResultVO<Record> result = new PaginationResultVO<>(count, page.getPageSize(), page.getPageNo(), page.getPageTotal(), list);
		return result;
	}

	/**
	 * 新增
	 */
	@Override
	public Long add(Record bean){
		return recordMapper.insert(bean);
	}

	/**
	 * 新增或更新
	 */
	@Override
	public Long addOrUpdate(Record bean){
		return recordMapper.insertOrUpdate(bean);
	}

	/**
	 * 批量新增
	 */
	@Override
	public Long addBatch(List<Record> listBean){
		if (listBean == null || listBean.isEmpty()) {
			return 0L;
		}
		return recordMapper.insertBatch(listBean);
	}

	/**
	 * 批量新增或更新
	 */
	@Override
	public Long addOrUpdateBatch(List<Record> listBean){
		if (listBean == null || listBean.isEmpty()) {
			return 0L;
		}
		return recordMapper.insertOrUpdateBatch(listBean);
	}

	/**
	 * 多条件更新
	 */
	@Override
	public Long updateByQuery(Record bean, RecordQuery query){
		return recordMapper.updateByQuery(bean, query);
	}

	/**
	 * 多条件删除
	 */
	@Override
	public Long deleteByQuery(RecordQuery query){
		return recordMapper.deleteByQuery(query);
	}

	/**
	 * 根据PRIMARY查询
	 */
	@Override
	public Record getRecordById(Integer id){
		return recordMapper.selectById(id);
	}

	/**
	 * 根据PRIMARY删除
	 */
	@Override
	public Long deleteRecordById(Integer id){
		return recordMapper.deleteById(id);
	}

	/**
	 * 根据PRIMARY更新
	 */
	@Override
	public Long updateRecordById(Record bean, Integer id){
		return recordMapper.updateById(bean, id);
	}

    @Override
    public void submit(Integer stuId, SubmitDto submitDto) {
		RecordQuery recordQuery = new RecordQuery();
		recordQuery.setStuId(stuId);
		recordQuery.setAid(submitDto.getAid());
		List<Record> recordList = recordMapper.selectList(recordQuery);
		// 实际上肯定有签到记录，因为一发布就把签到记录存到数据库了
		if (recordList == null || recordList.isEmpty()){
			throw new BusinessException(ResponseCodeEnum.CODE_600);
		}
		// 拿到签到类型
		Activity activity = activityMapper.selectById(submitDto.getAid());
		String type = activity.getType();

		// 普通签到，存入照片
		if (ActivityTypeEnum.NORMAL_CHECK_IN.getCode().equals(type)){
			String key = Constants.REDIS_KEY + ActivityTypeRedisKeyEnum.NORMAL_CHECK_IN.getRedisKey() + ":" + submitDto.getAid();
			String picture = submitDto.getAdditionInfo().getPicture();

			if (StringTools.isEmpty(picture)){
				throw new BusinessException("请上传图片");
			}

			redisComponent.setCommon(key,picture);
		}

		// 手势签到，对比
		if (ActivityTypeEnum.GESTURE_CHECK_IN.getCode().equals(type)){
			String key = Constants.REDIS_KEY + ActivityTypeRedisKeyEnum.GESTURE_CHECK_IN.getRedisKey() + ":" + submitDto.getAid();
			List<Integer> gesture = submitDto.getAdditionInfo().getGesture();

			// 拿出手势
			Map commonMap = redisComponent.getCommonMap(key);

			AdditionInfoDto additionInfoDto = new AdditionInfoDto();
			BeanUtil.fillBeanWithMap(commonMap,additionInfoDto,false);
			List<Integer> list = additionInfoDto.getGesture();

			for (int i = 0; i < gesture.size(); i++) {
				if (!gesture.get(i).equals(list.get(i))){
					throw new BusinessException("手势错误");
				}
			}
		}

		if (ActivityTypeEnum.LOCATION_CHECK_IN.getCode().equals(type)){
			String key = Constants.REDIS_KEY + ActivityTypeRedisKeyEnum.LOCATION_CHECK_IN.getRedisKey() + ":" + submitDto.getAid();
			LocationDto locationDto = submitDto.getAdditionInfo().getLocationDto();
			Double latitude = locationDto.getLatitude();
			Double longitude = locationDto.getLongitude();
			Integer range = locationDto.getRange();
			// TODO 是否在范围内
		}

		if (ActivityTypeEnum.QR_CODE_CHECK_IN.getCode().equals(type)){
			String key = Constants.REDIS_KEY + ActivityTypeRedisKeyEnum.QR_CODE_CHECK_IN.getRedisKey() + ":" + submitDto.getAid();
			String qrcode = submitDto.getAdditionInfo().getQrcode();

			Map commonMap = redisComponent.getCommonMap(key);
			AdditionInfoDto additionInfoDto = new AdditionInfoDto();
			BeanUtil.fillBeanWithMap(commonMap,additionInfoDto,false);
			String redisQrcode = additionInfoDto.getQrcode();

			if (!redisQrcode.equals(qrcode)){
				throw new BusinessException("二维码错误");
			}
		}

		if (ActivityTypeEnum.CODE_CHECK_IN.getCode().equals(type)){
			String key = Constants.REDIS_KEY + ActivityTypeRedisKeyEnum.CODE_CHECK_IN.getRedisKey() + ":" + submitDto.getAid();
			String code = submitDto.getAdditionInfo().getCode();

			Map commonMap = redisComponent.getCommonMap(key);
			AdditionInfoDto additionInfoDto = new AdditionInfoDto();
			BeanUtil.fillBeanWithMap(commonMap,additionInfoDto,false);
			String redisCode = additionInfoDto.getCode();

			if (!redisCode.equals(code)){
				throw new BusinessException("签到码错误");
			}
		}

		// 修改签到状态
		Record record = new Record();
		// 判断是否是迟到状态
		Date endTime = activity.getEndTime();
		Integer lateTimeMinutes = activity.getLateTime(); // 单位：分钟
		long lateDeadlineMillis = endTime.getTime() + ((long) lateTimeMinutes) * 60 * 1000;
		Date lateDeadline = new Date(lateDeadlineMillis);
		Date now = new Date();

		String status = RecordStatusEnum.SUCCESS.getCode();

		if (now.after(endTime) && !now.after(lateDeadline)) {
			status = RecordStatusEnum.LATE.getCode();
		}
		record.setStatus(status);
		record.setCreateTime(new Date());
		recordMapper.updateByQuery(record,recordQuery);
    }
}